﻿package game 
{
	/**
	 * ...
	 * @author Doan Nguyen Thuy Nha Truc (Bamboo)	
	 */
	import flash.events.EventDispatcher;
	import flash.net.NetConnection;
	import flash.events.NetStatusEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Responder;	
	import game.events.EventData;
	import game.exchangeddata.ChannelInfo;
	import flash.utils.setTimeout;
	import flash.utils.clearTimeout;
	public class ChannelControl extends EventDispatcher
	{
		
		public function ChannelControl() 
		{
			
		}
		
		public var channelInfo:ChannelInfo;
		private static const fms:String = "fms";
		private var clientObjectBw:Object;
		private var clientObjectTime:Object;
		
		public var ncChannelTime:NetConnection;
		public var ncChannelBw:NetConnection;
		private var setCheckConnect:uint;
		
		private var _fmsChannel:String;
		public function initFmsMonitor(str:String):void {
			//trace("initFmsMonitor:" + str);
			this.channelInfo = new ChannelInfo();
			this.channelInfo.init(str);
			checkTime(this.channelInfo.listChannel[this.channelInfo.countCheckFms][ChannelControl.fms]);
		}
		
		private function checkBw(rtmpStr:String):void {
			trace("checkBw:" + rtmpStr + "this.channelInfo.countCheckFms:" +this.channelInfo.countCheckFms);
			clientObjectBw = new Object();
			clientObjectBw["onBWDone"] = onBWDone;
			clientObjectBw["onFI"] = onFI;
			clientObjectBw["onMetaData"] = onMetaData;
			
			ncChannelBw = new NetConnection();
			ncChannelBw.client = clientObjectBw;
			
			ncChannelBw.addEventListener(NetStatusEvent.NET_STATUS, netStatusBwHdl);
			ncChannelBw.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHdl);
			var rtmp:String = rtmpStr.substr(0, rtmpStr.length - 4);
			rtmp = rtmp + "bandwidth";
			trace("rtmp:" + rtmp);
			ncChannelBw.connect(rtmp);
			setCheckConnect = setTimeout(closeCheckBw, 4000);
			
		}
		
		
		
		private function closeCheckBw():void {			
			ncChannelBw.close();
			this.channelInfo.countCheckFms++;
			trace("closeCheckBw" + this.channelInfo.countCheckFms);
			if (this.channelInfo.countCheckFms < this.channelInfo.listTimeChannel.length) {
				checkBw(this.channelInfo.listChannel[this.channelInfo.countCheckFms][ChannelControl.fms]);
			}else {
				reChooseChannel();
			}
		}
		
		
		
		private function netStatusBwHdl(e:NetStatusEvent):void 
		{
			var event:EventData;
			trace("netStatusBwHdl:"+e.info.code);
			switch(e.info.code) {
				case "NetConnection.Connect.Success":
					ncChannelBw.call("checkBandwidth", new Responder(successCallFMS, failCallFMS));
					clearTimeout(setCheckConnect);
					break;
				case "NetConnection.Connect.Failed":
					break;
				case "NetConnection.Connect.Rejected":
					break;
				case "NetConnection.Connect.Closed":
					break;
			}
			
		}
		
		
		
		
		private function reChooseChannel():void
		{
			trace("Re Choose Channel");
			if (this.channelInfo.listBwChannel.length > 0) {
				//update fms to load video LISTBWCHANNEL
				//load video, update UI channel
				activeVideoChannel(this.channelInfo.listBwChannel[this.channelInfo.listBwChannel.length - 1][ChannelControl.fms]);
			}
			else {
				//update fms to load video LISTCHANNEL
				//load video, update UI channel
				activeVideoChannel(this.channelInfo.listChannel[0][ChannelControl.fms]);
			}
		}
		
		
		private function checkTime(rtmp:String)
		{
			//trace("checktime:" + rtmp);
			ncChannelTime = new NetConnection();
			clientObjectTime = new Object();
			ncChannelTime.client = clientObjectTime;
			
			clientObjectTime["onBWDone"] = onBWDone;
			clientObjectTime["onFI"] = onFI;
			clientObjectTime["onMetaData"] = onMetaData;
			
			
			ncChannelTime.addEventListener(NetStatusEvent.NET_STATUS, netStatusTimeHdl);
			ncChannelTime.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHdl);
			ncChannelTime.connect(rtmp);
			this.channelInfo.lastTimeConnect = this.channelInfo.getTimeCurrent();
			setCheckConnect = setTimeout(closeCheckTime, 1000); 
		}	
		
		
		/**
		 * close checkTime if Responder >1000
		 */
		private function closeCheckTime():void {
			ncChannelTime.close();
			//trace("closeCheckTime" + this.channelInfo.countCheckFms +"fail");
			this.channelInfo.countCheckFms++;
			if (this.channelInfo.countCheckFms < this.channelInfo.listChannel.length) {
				checkTime(this.channelInfo.listChannel[this.channelInfo.countCheckFms][ChannelControl.fms]);
			}else {
				if (this.channelInfo.listTimeChannel.length == 0)
					this.channelInfo.listTimeChannel = this.channelInfo.randomArray(this.channelInfo.listChannel);	
				activeVideoChannel(this.channelInfo.listTimeChannel[0][ChannelControl.fms]);// check time and do only
				//checkBW
				//this.channelInfo.countCheckFms = 0;
				//checkBw(channelInfo.listTimeChannel[this.channelInfo.countCheckFms][ChannelControl.fms]);//not check BW
			}
		}
		
		private function netStatusTimeHdl(e:NetStatusEvent):void {		
			var event:EventData;
			//trace("netStatusNcIdHdl:"+e.info.code);
			switch(e.info.code) {
				case "NetConnection.Connect.Success":
					clearTimeout(setCheckConnect);
					this.channelInfo.getTimeSuccess();
					if (this.channelInfo.countCheckFms < this.channelInfo.listChannel.length) {
						checkTime(this.channelInfo.listChannel[this.channelInfo.countCheckFms][ChannelControl.fms]);
					}else
					{	// done checkTime and had fms that connected by time < 1000
						activeVideoChannel(this.channelInfo.listTimeChannel[0][ChannelControl.fms]);// check time and do only
						//checkBW
						//this.channelInfo.countCheckFms = 0;
						//checkBw(channelInfo.listTimeChannel[this.channelInfo.countCheckFms][ChannelControl.fms]);
						
					}
					break;
				case "NetConnection.Connect.Failed":
					break;
				case "NetConnection.Connect.Rejected":
					break;
				case "NetConnection.Connect.Closed":
					break;
			}
		}
		
		private function securityErrorHdl(e:SecurityErrorEvent):void {
			trace("SecurityErrorHdl: " + e);
		}
		
		private function successCallFMS(strMsg:String):void {
			trace("successCallFMS");
		}
		
		
		private function failCallFMS(strMsg:String):void {
			trace("failCallFMS");
		}
		
		public function onBWCheck(data:String):void {
			trace("onBWCheck");
		}
		
		public function onBWDone(...rest):void {
			trace("onBWDone ??"+ rest.length);			
			if(rest.length != 0){
				var temp:int = int(rest[0]);
				if (temp > 250) {
					//update fms to load video LISTTIMECHANNEL
					//load video, update UI channel					
					activeVideoChannel(this.channelInfo.listTimeChannel[this.channelInfo.countCheckFms][ChannelControl.fms]);
				}else {					
					this.channelInfo.getBwSuccess(rest[0]);
					if (this.channelInfo.countCheckFms < this.channelInfo.listTimeChannel.length)
						checkBw(channelInfo.listTimeChannel[this.channelInfo.countCheckFms][ChannelControl.fms]);
					else
						reChooseChannel();
				}				
			}else{
				trace("Nothing onBWDone");
			}
		}
		
		public function onFI(...rest):void 
		{
			trace("onFI");
		}
		
		public function onMetaData(...rest):void 
		{
			trace("onMetaData");
		}

		public function activeVideoChannel(nameFmsChannel:String) {
			//trace("activeVideoChannel" + nameFmsChannel);
			this.fmsChannel = nameFmsChannel;
			GlobalVariables.fmsChannel = nameFmsChannel;
			dispatchEvent(new EventData(EventData.SET_FMS_CHANNEL, false));
					
		}
		
		public function get fmsChannel():String{
			return _fmsChannel;
		}
		
		public function set fmsChannel(value:String):void {
			this._fmsChannel = value;
		}
		
	}


}